package com.ant.storage.service.impl;


import com.ant.storage.common.ResultCode;
import com.ant.storage.common.ResultVo;
import com.ant.storage.dto.ProDto;
import com.ant.storage.handler.AntException;
import com.ant.storage.mapper.CommodityMapper;
import com.ant.storage.mapper.InventoryLogMapper;
import com.ant.storage.mapper.InventoryMapper;
import com.ant.storage.mapper.PlannedProcurementMapper;
import com.ant.storage.pojo.*;
import com.ant.storage.service.IInventoryLogService;
import com.ant.storage.service.IInventoryService;
import com.ant.storage.service.IPlannedProcurementService;
import com.ant.storage.service.ISupplierPayListService;
import com.ant.storage.utils.DateFormat;
import com.ant.storage.vo.ProVo;
import com.ant.storage.vo.ProcurementVo;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import org.apache.commons.lang3.StringUtils;
import org.apache.poi.ss.usermodel.CellType;
import org.apache.poi.xssf.usermodel.XSSFCell;
import org.apache.poi.xssf.usermodel.XSSFRow;
import org.apache.poi.xssf.usermodel.XSSFSheet;
import org.apache.poi.xssf.usermodel.XSSFWorkbook;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.multipart.MultipartFile;

import javax.annotation.Resource;
import javax.servlet.ServletContext;
import java.io.IOException;
import java.math.BigDecimal;
import java.math.RoundingMode;
import java.text.SimpleDateFormat;
import java.util.*;
import java.util.stream.Collectors;

/**
 * <p>
 * 服务实现类
 * </p>
 *
 * @author hzd
 * @since 2023-07-26
 */
@Service
public class PlannedProcurementServiceImpl extends ServiceImpl<PlannedProcurementMapper, PlannedProcurement> implements IPlannedProcurementService {

    @Autowired
    private IInventoryLogService logService;

    @Resource
    private CommodityMapper commodityMapper;

    @Resource
    private InventoryMapper inventoryMapper;

    @Resource
    private InventoryLogMapper inventoryLogMapper;

    @Autowired
    private ISupplierPayListService payListService;

    @Autowired
    private IInventoryService inventoryService;

    @Autowired
    public ServletContext servletContext;


    @Override
    @Transactional(rollbackFor = Exception.class)
    public ResultVo upload(MultipartFile file) {
        UserInfo userInfo = (UserInfo) servletContext.getAttribute("userInfo");
        PlannedProcurement procurement;//定义员工POJO类
        List<PlannedProcurement> list = new ArrayList<>();//解析出来的封装好要返回的对象
        SimpleDateFormat format = new SimpleDateFormat("yyyy-mm-dd");//插入数据库时，需要日期格式转换
        if (file.isEmpty()) {//先判断客户端上传的excel有没有效
            throw new RuntimeException("文件错误");
        }
        try {
            //获得上传的excel文件 XSSFWorkbook
            //    HSSFWorkbook workbook = new HSSFWorkbook(new POIFSFileSystem(file.getInputStream()));
            XSSFWorkbook workbook = new XSSFWorkbook(file.getInputStream());
            //获取第一个sheet
            XSSFSheet sheet = workbook.getSheetAt(0);
            //获取行数
            int rowNums = sheet.getPhysicalNumberOfRows();
            //遍历行数
            for (int i = 1; i < rowNums; i++) {
                procurement = new PlannedProcurement();
                //得到该行的数据
                XSSFRow row = sheet.getRow(i);
                if (row != null) {
                    //获得该行的单元格数量，并遍历出单元格
                    int cellNums = row.getPhysicalNumberOfCells();
                    for (int j = 0; j < cellNums; j++) {
                        XSSFCell cell = row.getCell(j);
                        if (cell != null) {
                            //开始填装Emp实体属性
                            cell.setCellType(CellType.STRING);
                            String value = cell.getStringCellValue();
                            //如果值是空的则空字符串
                            if (value == null || StringUtils.isEmpty(value)) {
                                value = "";
                            }

                            try {
                                Commodity one = new Commodity();  //根据商品名称查询
                                if (j == 0) {
                                    //判断商品是否存在
                                    one = inventoryService.getOneCommodityId(value);  //根据商品名称查询
                                    System.out.println(one);
                                    if (one == null) {
                                        throw new AntException(201, value + "商品不存在");
                                    }
                                }

                                //procurement.setCommodityName(value);
                                //每一个字段对应的index
                                switch (j) {
                                    case 0:
                                        procurement.setCommodityId(one.getCommodityId());
                                        procurement.setCommodityName(one.getCommodityName());
                                        procurement.setCommodityType(one.getCommodityType());
                                        procurement.setCommodityUnit(one.getCommodityUnits());
                                        break;
                                    case 1:
                                        procurement.setInventoryBalance(value);
                                        break;
                                    case 2:
                                        procurement.setPlannedInventory(value);
                                        break;
                                    case 3:
                                        procurement.setUnitPrice(new BigDecimal(value));
                                        break;
                                    case 4:
                                        procurement.setPurchaseAmount(value);
                                        break;
                                    case 5:
                                        procurement.setRemarks(value);
                                        break;
                                }
                                procurement.setCityId(userInfo.getCityId());
                                procurement.setHandlers("admin");
                                procurement.setPlannedNumber(DateFormat.getCurrentDate());
                                procurement.setProcuredStates(0);
                                procurement.setCreationTime(new Date());
                            } catch (Exception e) {
                                throw new AntException(201, value+"商品不存在");
                            }
                        }
                    }
                    //一个完整emp
                    // 将添加好的emp添加到list
                    System.out.println(procurement);
                    this.baseMapper.insert(procurement);
                    list.add(procurement);
                }
            }
            return ResultVo.success("操作成功");
        } catch (IOException e) {
            e.printStackTrace();
            throw new AntException(ResultCode.FAILURE.getCode(), "操作失败" );
        }
    }

    @Override
    public ResultVo getByPlannedNumber() {
        return ResultVo.success("操作成功", this.baseMapper.getByPlannedNuber());
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public ResultVo saveWarehousing(List<ProVo> voList) {
        if (voList.size() > 0) {
            voList.stream().forEach(vo -> {
                if (vo.getProcurementVoList().size() > 0) {
                    UserInfo userInfo = (UserInfo) servletContext.getAttribute("userInfo");
                    vo.getProcurementVoList().stream().map(item -> {
                        Inventory selectOne = inventoryMapper.selectOne(new QueryWrapper<Inventory>()
                                .eq("warehouse_id", vo.getWarehouseId())
                                .eq("commodity_id", vo.getCommodityId()));
                        Inventory inventory = new Inventory();
                        if (selectOne != null) {
                            BigDecimal GoodsAmount = selectOne.getGoodsAmount()
                                    .add(new BigDecimal(item.getNumber()));
                            GoodsAmount.setScale(2, BigDecimal.ROUND_HALF_UP);
                            inventory.setGoodsAmount(GoodsAmount);
                            //计算库存的价格
                            BigDecimal bigDecimal = CalculateUnitPrices(selectOne, item);
                            inventory.setGoodsPrice(bigDecimal);
                            inventory.setId(selectOne.getId());
                            inventoryMapper.updateById(inventory);
                        } else {
                            inventory.setWarehouseId(vo.getWarehouseId());
                            inventory.setCommodityId(vo.getCommodityId());
                            inventory.setGoodsAmount(new BigDecimal(item.getNumber()).setScale(2,
                                    BigDecimal.ROUND_HALF_UP));
                            inventory.setGoodsPrice(item.getPrice());
                            inventory.setCreatorBy(userInfo.getNameId().toString());
                            inventory.setCreationTime(new Date());
                            inventoryMapper.insert(inventory);
                        }
                        item.setRemark(vo.getRemark());
                        insertLoginLog(inventory.getId(), item, vo.getId(), vo.getWarehouseId(),
                                item.getPurchaserId(), userInfo.getNameId());
                        if (item.getSupplierId() != null) {
                            SupplierPayList payList = new SupplierPayList();
                            payList.setSupplierId(item.getSupplierId());
                            payList.setPlannedId(vo.getId());
                            payList.setPrice(item.getPrice());
                            payList.setAmount(item.getNumber());
                            payList.setTotalPrice(new BigDecimal(item.getNumber()).multiply(new BigDecimal(String.valueOf(item.getPrice()))));
                            payList.setPurchaserId(item.getPurchaserId());
                            payList.setHandleId(userInfo.getNameId());
                            payList.setCommodityId(vo.getCommodityId());
                            payList.setCreationTime(new Date());
                            payListService.save(payList);
                        }
                        return log;
                    }).collect(Collectors.toList());
                    PlannedProcurement procurement = new PlannedProcurement();
                    procurement.setId(vo.getId());
                    procurement.setProcuredStates(1);
                    this.baseMapper.updateById(procurement);
                } else {
                    throw new AntException(ResultCode.FAILURE.getResultCode(), "采购数据不能为空");
                }
            });
        } else {
            return ResultVo.fail("数据不能为空");
        }
        return ResultVo.success("操作采购");
    }


    @Override
    public List<PlannedProcurement> getPlannedList(ProDto dto) {
        UserInfo userInfo = (UserInfo) servletContext.getAttribute("userInfo");
        QueryWrapper<PlannedProcurement> wrapper = new QueryWrapper<>();
        if (userInfo.getRoles().equals("admin")) {
            wrapper.eq("city_id", userInfo.getCityId());
        }
        if (StringUtils.isNotEmpty(dto.getPlannedName())) {
            wrapper.like("commodity_name", dto.getPlannedName().trim());
        }
        if (StringUtils.isNotEmpty(dto.getPlannedNumber())) {
            wrapper.eq("planned_number", dto.getPlannedNumber().trim());
        }


        List<PlannedProcurement> list = this.baseMapper.selectList(wrapper);
        list.stream().forEach(item -> {
            List<InventoryLog> inventoryLogs = logService.list(new QueryWrapper<InventoryLog>().eq("planned_id",
                    item.getId()));
            item.setDetailslist(inventoryLogs);
        });
        return list;
    }

    @Override
    public Map<String, Object> getPlannedPageList(ProDto dto) {
        QueryWrapper<PlannedProcurement> wrapper = new QueryWrapper<>();
        if (StringUtils.isNotEmpty(dto.getPlannedNumber())) {
            wrapper.eq("planned_number", dto.getPlannedNumber().trim());
        }
        if (StringUtils.isNotEmpty(dto.getPlannedName())) {
            wrapper.like("commodity_name", dto.getPlannedName().trim());
        }
        if (dto.getProcuredStates() != null) {
            wrapper.eq("procured_states", dto.getProcuredStates());
        }

        UserInfo userInfo = (UserInfo) servletContext.getAttribute("userInfo");
        if (userInfo.getRoles() == null || userInfo.getRoles().equals("admin")) {
            wrapper.eq("city_id", userInfo.getCityId());
        }
        List<PlannedProcurement> list = this.baseMapper.selectList(wrapper);
        list.stream().forEach(item -> {
            List<InventoryLog> inventoryLogs = logService.list(new QueryWrapper<InventoryLog>().eq("planned_id",
                    item.getId()));
            item.setDetailslist(inventoryLogs);
        });
        Map<Integer, Double> collect =
                list.stream().collect(Collectors.groupingBy(PlannedProcurement::getCommodityType,
                        Collectors.summingDouble(p -> Double.parseDouble(p.getPurchaseAmount()))));
        double sum = collect.values().stream().collect(Collectors.summarizingDouble(s -> s.doubleValue())).getSum();
        Map<String, Object> map = new HashMap<>();
        map.put("data", list);
        map.put("countList", collect);
        map.put("countToal", new BigDecimal(sum).setScale(2, RoundingMode.UP).doubleValue());

        return map;
    }

    /**
     * 计算价格
     *
     * @param inventory
     * @param vo
     * @return
     */
    private BigDecimal CalculateUnitPrices(Inventory inventory, ProcurementVo vo) {
        try {
            // 计算库存单价
            BigDecimal GoodsAmount = inventory.getGoodsAmount();
            BigDecimal GoodsPrice = inventory.getGoodsPrice() == null ? new BigDecimal("0") : inventory.getGoodsPrice();
            BigDecimal unitPrice1 = GoodsAmount.multiply(GoodsPrice).setScale(5, BigDecimal.ROUND_HALF_UP);
            // 计算入库单价
            BigDecimal CommodityAmount = new BigDecimal(vo.getNumber());
            BigDecimal CommodityPrice = vo.getPrice() == null ? new BigDecimal("0") : vo.getPrice();
            BigDecimal unitPrice2 = CommodityAmount.multiply(CommodityPrice).setScale(5, BigDecimal.ROUND_HALF_UP);
            BigDecimal totalPrice = unitPrice1.add(unitPrice2);
            BigDecimal totalAmout = GoodsAmount.add(CommodityAmount);

            if (totalPrice.compareTo(BigDecimal.ZERO) == 0) {
                return new BigDecimal("0");
            }
            BigDecimal unitPrice = totalPrice.divide(totalAmout, 5, BigDecimal.ROUND_HALF_UP);
            return unitPrice;
        } catch (Exception e) {
            throw new AntException(ResultCode.FAILURE.getResultCode(), e.getMessage());
        }

    }

    /**
     * 添加入库日志记录
     */
    public void insertLoginLog(Integer inventoryId, ProcurementVo vo, Integer plannedId,
                               Integer wid, Integer PurchaserId, Integer uid) {
        InventoryLog log = new InventoryLog();
        log.setWarehouseId(wid);
        log.setInventoryId(inventoryId);
        log.setPurchaserId(PurchaserId);
        log.setGoodsAmount(vo.getNumber()); // 入库数量
        log.setGoodsPrice(vo.getPrice()); // 价格
        // log.setStockState(new BigDecimal(vo.getNumber()).compareTo(BigDecimal.ZERO) > 0 ? 1 : 2); // 入库
        log.setStockState(1); // 入库
        log.setPlannedId(plannedId);
        log.setPurchaseOrdersId(plannedId);
        log.setChannelId(vo.getChannelId());
        // log.setRemark(new BigDecimal(vo.getNumber()).compareTo(BigDecimal.ZERO) > 0?"计划采购入库":"退货出库");
        log.setRemark(new BigDecimal(vo.getNumber()).compareTo(BigDecimal.ZERO) > 0 ? "计划采购入库;" + vo.getRemark() :
                "退货出库" + vo.getRemark());
        log.setCreatorBy(uid.toString());
        log.setCreationTime(new Date());
        inventoryLogMapper.insert(log);
    }
}
